package com.chinaunicom.emergency.action;

import com.alibaba.fastjson.JSONObject;
import com.chinaunicom.emergency.annotation.Permission;
import com.chinaunicom.emergency.constant.ConstantUtil;
import com.chinaunicom.emergency.exception.CheckException;
import com.chinaunicom.emergency.model.Dictionary;
import com.chinaunicom.emergency.model.UserRole;
import com.chinaunicom.emergency.model.YjglUser;
import com.chinaunicom.emergency.repository.DictionaryRepository;
import com.chinaunicom.emergency.repository.OrgRepository;
import com.chinaunicom.emergency.repository.UserRoleRepository;
import com.chinaunicom.emergency.repository.UsersRepository;
import com.chinaunicom.emergency.security.RsaUtil;
import com.chinaunicom.emergency.service.RedisService;
import com.chinaunicom.emergency.service.UserService;
import com.chinaunicom.emergency.util.Assert;
import com.chinaunicom.emergency.util.UpdateUtil;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 用户api
 * @Author liliang
 * @Date 2019/12/17 15:05
 * @Version 1.0
 */
@RestController
@Api(tags = {"用户管理"})
@RequestMapping("/api/user")
@Log4j2
@RefreshScope
public class UserAction extends BaseAction {

    @Autowired
    PasswordEncoder passwordEncoder;
    @Autowired
    UsersRepository usersRepository;
    @Autowired
    UserService userService;
    @Autowired
    OrgRepository orgRepository;
//    @Autowired
//    OrgService orgService;
    @Autowired
    UserRoleRepository userRoleRepository;
    @Autowired
    DictionaryRepository dictionaryRepository;

    @Autowired
    RedisService redisService;

    @ApiOperation("用户新增")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorization", value = "token", required = true, dataType = "String", paramType = "header")
    })
    @Permission("user:add")
    @PostMapping(value = "/add")
    public Object add(@RequestBody YjglUser user) throws CheckException {
        Assert.isBlank(user.getUserName(), "用户账号不能为空");
        Assert.isBlank(user.getRealName(), "用户名称不能为空");
        YjglUser existUser = usersRepository.findYjglUserByUserNameAndIsSoftDel(user.getUserName(),0);
        Assert.isNotNull(existUser,"该账号已存在,请勿重复创建");
        if(StringUtils.isBlank(user.getPassword())){
            user.setPassword(passwordEncoder.encode("123456"));
        }
        user.setEnabled(1);
        user.setAccountIsNotExpired(1);
        user.setCredentialIsNotExpired(1);
        user.setAccountIsNotLocked(1);
        user.setIsSoftDel(0);
        user.setCreateBy(getCurrUserId());
        user.setCreateTime(new Date());
        usersRepository.save(user);
        return success();
    }

    @ApiOperation("用户修改")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorization", value = "token", required = true, dataType = "String", paramType = "header")
    })
    @Permission("user:update")
    @PutMapping(value = "/update")
    public Object update(@RequestBody YjglUser user) throws CheckException {
        Assert.isBlank(user.getUserName(), "用户账号不能为空");
        Assert.isBlank(user.getRealName(), "用户名称不能为空");
        Assert.isBlank(user.getPid(), "用户id不能为空");
        YjglUser oldUser = usersRepository.findYjglUserByPidAndIsSoftDel(user.getPid(),0);
        Assert.isNull(oldUser,"该用户不存在,修改失败");
        Assert.isNotEquals(user.getUserName(),oldUser.getUserName(),"用户名无法修改,请重新填写!");

        user.setUpdateBy(getCurrUserId());
        user.setUpdateTime(new Date());
        user.setPassword(null);
        UpdateUtil.copyNullProperties(oldUser,user);
        usersRepository.save(user);
        return success();
    }

    /**
     * type 0 密码修改，1锁定账户，2解锁账户
     * @param user
     * @param type
     * @return
     * @throws CheckException
     */
    @ApiOperation("用户密码/锁定状态修改")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorization", value = "token", required = true, dataType = "String", paramType = "header")
    })
    @Permission("user:updatePassLock")
    @PutMapping(value = "/updatePassLock")
    public Object update(@RequestBody YjglUser user, @RequestParam(value = "type") Integer type) throws Exception {
        Assert.isNull(type, "修改类型不能为空");
        Assert.isBlank(user.getPid(), "用户id不能为空");
        YjglUser oldUser = usersRepository.findYjglUserByPidAndIsSoftDel(user.getPid(),0);
        Assert.isNull(oldUser,"该用户不存在,修改失败");
        if(0 == type){
            Assert.isBlank(user.getOldPassword(),"原密码不能为空");
            Assert.isBlank(user.getPassword(),"新密码不能为空");
            String decryOldPassword = RsaUtil.decryptByPrivateKey(RsaUtil.getPrivateKeyStr(), user.getOldPassword());
            boolean check = passwordEncoder.matches(decryOldPassword,oldUser.getPassword());
            if(!check){
                throw new CheckException("旧密码错误，修改密码失败");
            }
            oldUser.setOldPassword(oldUser.getPassword());
            oldUser.setPassword(user.getPassword());
        }else{
            if(1 == type){
                oldUser.setEnabled(1);
                oldUser.setAccountIsNotLocked(1);
                //用户锁定时，需要清除用户账号token信息
                userService.deleteUserToken(user.getPid());
            }else  if(2 == type){
                oldUser.setEnabled(0);
                oldUser.setAccountIsNotLocked(0);
            }
        }
        oldUser.setUpdateBy(getCurrUserId());
        oldUser.setUpdateTime(new Date());
        usersRepository.save(oldUser);
        return success();
    }

    @ApiOperation("用户删除")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorization", value = "token", required = true, dataType = "String", paramType = "header")
    })
    @Permission("user:delete")
    @DeleteMapping(value = "/delete")
    public Object delete(@RequestParam(value = "pid") String pid) throws CheckException {
        Assert.isBlank(pid, "用户id不能为空");
        YjglUser oldUser = usersRepository.findYjglUserByPidAndIsSoftDel(pid,0);
        Assert.isNull(oldUser,"该用户不存在,删除失败");
        oldUser.setDeleteBy(getCurrUserId());
        oldUser.setIsSoftDel(1);
        oldUser.setEnabled(0);
        oldUser.setDeleteTime(new Date());
        //删除用户同时删除角色
        userService.delete(oldUser);
        return success();
    }


    @ApiOperation("单个用户明细查看")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorization", value = "token", required = true, dataType = "String", paramType = "header")
    })
    @Permission("user:detail")
    @GetMapping(value = "/{pid}")
    public Object findByPid(@PathVariable String pid) throws CheckException {
        Assert.isBlank(pid, "用户id不能为空");
        YjglUser user = usersRepository.findYjglUserByPidAndIsSoftDel(pid,0);
        setUserExtend(user);
        return success(user);
    }

    /**
     * 翻译用户表中关联字段
     * @param user
     */
    private void setUserExtend(YjglUser user) {
        if(null != user){
            if(StringUtils.isNotBlank(user.getOrgId())){
                user.setOrgNameStr(getOrgNameByOrgId(user.getOrgId()));
            }
            user.setPassword(null);
            user.setOldPassword(null);
        }

    }

    /**
     * 根据字典表pid获取字典值
     * @param pid
     * @return
     */
    private String getDicValueByPid(String pid){
        Dictionary dictionary = dictionaryRepository.findByPidAndIsSoftDel(pid,0);
        return null == dictionary ? null : dictionary.getDicValue();
    }


    public String getOrgNameByOrgId(String orgIds){
        String orgName = orgIds;
        if(StringUtils.isNotEmpty(orgName)){
            List<String> orgIdList = Arrays.asList(orgName.split(","));
            orgName = "";
            if(!CollectionUtils.isEmpty(orgIdList)){
                for(String orgId : orgIdList){
                    if(!redisService.hasHashField(ConstantUtil.PREFIX_ORG_TREE+":ORGID_NAMESTR",orgId)){
//                        orgService.updateRedis(true);
                    }
                    String oldOrgNameStr = (String)redisService.getHash(ConstantUtil.PREFIX_ORG_TREE+":ORGID_NAMESTR",orgId);
                    if(org.springframework.util.StringUtils.isEmpty(orgName)){
                        orgName = oldOrgNameStr;
                    }else {
                        orgName += ","+oldOrgNameStr;
                    }
                }
            }
        }
        return orgName;
    }


    @ApiOperation("分页查看用户列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorization", value = "token", required = true, dataType = "String", paramType = "header")
    })
    @Permission("user:page")
    @GetMapping(value = "/page")
    public Object findPage(@RequestParam(value = "limit", required = false) Integer limit,
                           @RequestParam(value = "page", required = false) Integer page,
                           @RequestParam(value = "userName", required = false) String userName,
                           @RequestParam(value = "realName", required = false) String realName
                            ) throws CheckException {
        Map<String, Object> para = new HashMap<>();
        para.put("limit", limit == null ? 10 : limit);
        para.put("page", page == null ? 1 : page);
        para.put("isSoftDel", 0);
        para.put("userName",userName);
        para.put("realName",realName);
        Sort sort = Sort.by(Sort.Direction.ASC, "orderNum");
        Page<YjglUser> pages = usersRepository.findAll(userService.findPageByCondition(para), getPageable(para, sort));
        if(null != pages){
            for (YjglUser user : pages){
                setUserExtend(user);
            }
        }
        return page(pages);
    }


    @ApiOperation("根据组织机构id分页查看用户列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorization", value = "token", required = true, dataType = "String", paramType = "header")
    })
    @Permission("user:listByOrg")
    @GetMapping(value = "/listByOrg")
    public Object listByOrg(@RequestParam(value = "limit", required = false) Integer limit,
                           @RequestParam(value = "page", required = false) Integer page,
                           @RequestParam(value = "orgId", required = false) String orgId,
                           @RequestParam(value = "userName", required = false) String userName,
                           @RequestParam(value = "realName", required = false) String realName
    ) throws CheckException {


        Map<String, Object> para = new HashMap<>();
        para.put("limit", limit == null ? 10 : limit);
        para.put("page", page == null ? 1 : page);
        para.put("isSoftDel", 0);
        para.put("userName",userName);
        para.put("realName",realName);
        if(StringUtils.isNotBlank(orgId)){
            List orgIdList = Lists.newArrayList();
            List<String> queryOrgIds = Lists.newArrayList();
            queryOrgIds.add(orgId);
            orgIdList = getLastChild(orgIdList,queryOrgIds);
            para.put("orgIdList",orgIdList);
        }
        Sort sort = Sort.by(Sort.Direction.ASC, "orderNum");
        Page<YjglUser> pages = usersRepository.findAll(userService.findPageByCondition(para), getPageable(para, sort));
        if(null != pages){
            for (YjglUser user : pages){
                setUserExtend(user);
            }
        }
        return page(pages);
    }

    //递归调用查询所有最子节点的机构id,
    public List<String> getLastChild(List orgList,List<String> orgs){
        for(String orgId : orgs){
            List<String> childs = orgRepository.findOrgIdByParentId(orgId);
            if(CollectionUtils.isEmpty(childs)){
                orgList.add(orgId);
            }else {
                getLastChild(orgList,childs);
            }
        }
        return orgList;
    }



    @ApiOperation("用户设置角色关系")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "token", required = true, paramType = "header", dataType = "String")
    })
    @Permission("user:setRole")
    @PostMapping(value = "/userRole")
    public Object setUserRole(@RequestParam(value = "roleId", required = true) String roleIds,
                              @RequestParam(value = "userName", required = true) String userName) throws Exception {
    	
        YjglUser user = usersRepository.findYjglUserByUserNameAndIsSoftDel(userName,0);
        Assert.isNull(user,"该用户不存在,无法关联角色");
        
        List<String> roleList = Arrays.asList(roleIds.split(","));
        List<String> oldRoleIdList = userRoleRepository.findRoleIdByUserId(user.getPid());
        if(CollectionUtils.isEmpty(roleList) && CollectionUtils.isEmpty(oldRoleIdList)){
            return success();
        }
        if(!CollectionUtils.isEmpty(oldRoleIdList) && !CollectionUtils.isEmpty(roleList)){
            if(oldRoleIdList.containsAll(roleList) && roleList.containsAll(oldRoleIdList)){
                return success();
            }
        }

        userService.setRole(user.getPid(),roleList,getCurrUserId());
        return success();
    }


    @ApiOperation("用户角色关系获取")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "Authorization", value = "token", required = true, paramType = "header", dataType = "String")
    })
    @Permission("user:getRole")
    @GetMapping(value = "/userRole/list")
    public Object getUserRole(@RequestParam String pid) throws CheckException {
        Assert.isBlank(pid,"用户id不能为空");
        List<UserRole> userRoleList = userRoleRepository.findByUserIdAndIsSoftDel(pid,0);
        return success(userRoleList);
    }

    
    @ApiOperation("修改密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorization", value = "token", required = true, dataType = "String", paramType = "header")
    })
    @Permission("user:updatePwd")
    @GetMapping(value = "/updatePwd")
    public Object updatePwd(@RequestParam String ciphertext) throws CheckException {
    	
        Assert.isBlank(ciphertext, "密码不能为空");
        String temp = RsaUtil.decryptByPrivateKey(RsaUtil.getPrivateKeyStr(), (String) ciphertext);
        JSONObject json = null;
        try {
            json = JSONObject.parseObject(temp);
        } catch (Exception e) {
            throw new UsernameNotFoundException("ciphertext解析失败");
        }
        String oldPassword = json.getString("oldPassword");
        String newPassword = json.getString("newPassword");
        String username = json.getString("userName");
        
        Assert.isBlank(username,"用户名不能为空");
        Assert.isBlank(newPassword,"新密码不能为空");
        Assert.isBlank(oldPassword,"原密码不能为空");
        if (StringUtils.isBlank(newPassword) || StringUtils.isBlank(username)) {
            throw new UsernameNotFoundException("用户名或密码不能为空，请检查");
        }
        try {
        	
        	YjglUser oldUser = usersRepository.findYjglUserByUserNameAndIsSoftDel(username,0);
            Assert.isNull(oldUser,"该用户不存在,修改失败");
            boolean check = passwordEncoder.matches(oldPassword,oldUser.getPassword());
            if(!check){
                throw new CheckException("旧密码错误，修改密码失败");
            }
            oldUser.setOldPassword(oldPassword);
            oldUser.setPassword(passwordEncoder.encode(newPassword));
           
            oldUser.setUpdateBy(getCurrUserId());
            oldUser.setUpdateTime(new Date());
            usersRepository.save(oldUser);

        } catch (Exception e) {
            log.info("修改失败：", e);
            throw new UsernameNotFoundException("修改失败");
        }

        return success();
    }
}
